package com.itcast.bulls.stock.quote.repository.trade;

import com.itcast.bulls.stock.common.utils.GlobalConstants;
import com.itcast.bulls.stock.entity.quote.TradeStockKline;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * <p>Description:  股票K线数据接口</p>
 * Spring 为我们提供了几个注解来支持 Spring Cache。其核心主要是 @Cacheable和 @CacheEvict。
 * 使用 @Cacheable 标记的方法在执行后Spring Cache将缓存其返回结果，
 * 而使用 @CacheEvict 标记的方法会在方法执行前或者执行后移除 Spring Cache 中的某些元素。
 */
@Repository
public interface TradeStockKlineRepository  extends PagingAndSortingRepository<TradeStockKline, Long>, JpaSpecificationExecutor<TradeStockKline> {

    /**
     * 保存K线数据
     *
     * 1.2 @CacheEvict
     *   - @CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发
     *   缓存的清除操作。@CacheEvict 可以指定的属性有 value、key、condition、allEntries和 beforeInvocation。
     *   其中 value、key 和 condition 的语义与 @Cacheable 对应的属性类似。即 value 表示清除操作是发生在哪些
     *   Cache 上的（对应Cache的名称）；key 表示需要清除的是哪个 key，如未指定则会使用默认策略生成的 key；
     *   condition 表示清除操作发生的条件。
     *
     * 单参数：cacheNames::arg
     * 无参数: cacheNames::SimpleKey [], 后面使用 SimpleKey []来补齐
     * 多参数: cacheNames::SimpleKey [arg1, arg2...]
     * 非基础对象：cacheNames::obj.toString()
     * ————————————————
     * 原文链接：https://blog.csdn.net/liuyueyi25/article/details/118422143
     *
     * 如果 entity 是被缓存的对象，并且没有指定key，那么Spring将使用对象的hashCode作为key来从缓存中清除条目。
     * value 属性指定 Cache 名称, value = GlobalConstants.STOCK_QUOTE_KLINE_KEY
     *   其表示当前方法的返回值是会被缓存在哪个 Cache 上的，对应 Cache 的名称。如：@Cacheable("cache1")
     *   Cache 是发生在 cache1 上的。
     *
     *   其可以是一个 Cache 也可以是多个 Cache，
     *   当需要指定多个 Cache 时其是一个数组。如：@Cacheable({"cache1", "cache2"}) Cache是发生在 cache1和 cache2 上的
     *
     * @param entity
     * @param <S>
     * @return
     */
    @Override
    @CacheEvict(GlobalConstants.STOCK_QUOTE_KLINE_KEY) // STOCK_QUOTE_KLINE_KEY = "stock:quote:kline"
    <S extends TradeStockKline> S save(S entity);

    /**
     * 根据时间段范围查询K线数据
     *
     * 1.1 @Cacheable
     *   - @Cacheable 可以标记在一个方法上，也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的，
     *   当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法，Spring 会在其被调用后
     *   将其返回值缓存起来，以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果，而不需要再次执行该方法。
     *   Spring 在缓存方法的返回值时是以键值对进行缓存的，值就是方法的返回结果，至于键的话，Spring又支持两种策略，
     *   默认策略和自定义策略，这个稍后会进行说明。需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存
     *   功能的。@Cacheable 可以指定三个属性，value、key 和 condition。
     *
     * @param stockCode
     * @param begin
     * @param end
     * @return
     */
    @Cacheable(value=GlobalConstants.STOCK_QUOTE_KLINE_KEY) // STOCK_QUOTE_KLINE_KEY = "stock:quote:kline"
    List<TradeStockKline> findAllByStockCodeAndTimeBetween(String stockCode, Long begin, Long end);

}
